
var selected_items = {};    // Selected items, grouped by bin.
var protocol = undefined;   // undefined -> No protocol selected.
var table = { items: [], columns: [], visible_cols: [] };
var protocol_items = undefined;
var experiment = undefined;
var table_page = 0;
var user_info = undefined;

var suggested_columns = ['Name', 'Gender', 'Age', 'Quantity'];

var column_priority = {
	'Patient': ['Type', 'Name', 'PRO ID', 'Gender', 'Race', 'Age', 'Diagnosis', 'Age at diagnosis', /*'Date of diagnosis', 'Date of death',*/ 'Cause of death',  'Other cancers', 'Family ID', /*'Watchful wait pre-treatment',*/ 'Primary treatment', 'Primary hormonal treatment', 'PSA ug/l', 'PSA-%', /*'AFOS', 'Creatine',*/ 'Date of progression'],
	
	'Visit': ['Patient > PRO ID', 'Patient > Year of death', 'Date of visit', 'Visit reason', 'PSA ug/l', 'PSA-%'],

	'Tissue': ['Patient > PRO ID', 'PAD ID', 'Origin', 'Histopathologic diagnosis', 'WHO grade', 'Gleason score', 'Perineural invasion', 'Tumor %', 'T-stage (pathologist)', 'N-stage (pathologist)'],
	
	'Primer': ['Template', 'Application', 'Target', 'Quantity', 'Target aberration', 'Strand', 'Sequence', 'Amplicon size'],
	
	'Transcriptome': ['Tissue > PAD ID', 'Platform', 'BAM file', 'Total reads', 'Mapped %', 'chrM %', 'Tissue > Origin', 'Tissue > Histopathologic diagnosis', 'Tissue > Gleason score', 'Tissue > Tumor %'],

	'Protocol': ['Selected', 'Name', 'Authors'],

	'Multielectrode array': ['ID', 'Tissue type', 'Plate code', 'Plate type', 'Author', 'Preparation date', 'hES line', 'Coating substrate', 'Coating details', 'Electrode layout'],

	'Unknown': []
};

var valid_item_types = {
	'Tissue': {'Anatomical site':"", 'Quantity':"", 'Gleason grade':"",
		'Gleason score':""},
	'Cell lysate': {},
	'DNA extract': {'Quantity':""},
	'RNA extract': {'Quantity':""},
	'Animal': {'Identifier':"", 'Species':"", 'Litter':"", 'Date of birth':"",
		'Date of death':"", 'Cause of death':""},
	'Patient': {'Name':"", 'Gender':"", 'Age':"", 'Race':"", 'Date of birth':"", 'Date of death':"", 'Cause of death':""},
	'Primer': {'Sequence':"", 'Target':"", 'Application':"", 'Amplicon size':""},
	'Multielectrode array': {
		'ID':"", 'Plate':"", 'Preparation date':"", 'Tissue type':"",
		'Author':"", 'hES line':"", 'Passage':"", 'Batch date':"", 'Plate type':"",
		'Coating substrate':"", 'Coating details':"",
		'N cells / MEA':"", 'Electrode layout':"", 'Discard DIV':"",
		'Adhesion':"", 'Cleaning agent':"", 'Cleaning time (h)':"", 'Plasma':"", 'Notes':""},
	'Plasmid': {},
	'Vector': {},
	'Protocol': {},
	'Excel': {}
};

var protocol_sample_texts ={
	"Protocol": "input Tissue {\n\tType = 'Tissue' \n\tQuantity > 0.000015\n\tisVolume(Quantity)\n\tprefer Quantity > 0.00005\n}\n\noutput Tissue -> DNA extract {\n\tTissue: link\n\tQuantity: volume(3 * Quantity)\n\tConcentration: concentration(Quantity / 15) \n}\n\noutput Tissue -> RNA extract {\n\tTissue: link\n\tQuantity: volume(5 * Quantity)\n}\n\nmodify Tissue {\n\tQuantity: mass(Quantity - 0.1)\n}\n\nsettings {\n\tKit: ['Qiagen DNA extraction kit', 'Illumina miRNA extraction kit'] \n\tDo phase X: true \n\tTrizol density: 10 ml - 25 ml\n\twater type: ['pure','tap']\n}",
	"Add_Item" :"output Mouse {\n\tCause of death: Cancer\n\tSpecies: Lab\n}\n",
	"Add_Linker": "output Patient -> DNA extract {\n\tType: DNA\n\t%Patient > PRO ID: Linker attribute\n\tSequence: TTGGAACCGTT\n}\noutput Patient -> RNA extract {\n\t%Patient > PRO ID: Linker attribute\n\tQuantity: 5ml\n\tCancer: Yes\n}\n"
};


var ITEMS_PER_PAGE = 1000;
var MAX_VISIBLE_COLS = 10;


//////////////////////
// HELPER FUNCTIONS //
//////////////////////

// Clean up string so that it can pass as an HTML identifier.
function c(str) {
	str = str.replace(' ', '_');
	str = str.replace('/', '_');
	str = str.replace('-', '_');
	return str;
}

function si(str) {
	var value = parseFloat(str);
	if(isNaN(value)) return str;
	return volumeConv(str);
}

function hidden_column(col) {
	if (col.indexOf('Protocol.') != -1) return true;
	if (col.indexOf('Experiment.') != -1) return true;
	if (col.match(/(^|> )id$/)) return true;
	if (col == 'Can edit' || col == 'Type' || col == 'bin') return true;
	return false;
}


// For loop with builtin hasOwnProperty() checks.
function for_each(obj, f) {
	for (key in obj) {
		if (obj.hasOwnProperty(key)) { f(obj[key], key); }
	}
}

function remove_children(node) {
	while (node.lastChild)
		node.removeChild(node.lastChild);
}

function volumeConv(str) {
	var units = {
		n: Math.pow(10, -9),
		u: Math.pow(10, -6),
		m: Math.pow(10, -3),
		c: Math.pow(10, -2),
		d: Math.pow(10, -1)
	};
	var value = parseFloat(str);
	var unit = str.replace(value, '').trim();
	var times = 1;
	if(parseFloat(unit) !== 0){
		times = units.hasOwnProperty(unit[0]) ? units[unit[0]] : 1;
	}
	return parseFloat((value * times).toFixed(9));
}

function sortItems(column, asc){
	if(asc){
		table.items.sort(function(a,b){
			if (!a.hasOwnProperty(column)) return 1;
			if (!b.hasOwnProperty(column)) return -1;
			var valueA = a[column];
			var valueB = b[column];
			if(valueA===valueB) return a.id > b.id ? 1 : -1;
			return valueA > valueB ? 1 : -1;
		});
	}else{
		table.items.sort(function(a,b){
			if (!a.hasOwnProperty(column)) return -1;
			if (!b.hasOwnProperty(column)) return 1;
			var valueA = a[column];
			var valueB = b[column];
			if(valueA===valueB) return a.id > b.id ? -1 : 1;
			return valueA > valueB ? -1 : 1;
		});
	}
}

function tableToTSV() {
	cols = table.columns;
	rows = table.items;
	str = '' + cols[0];
	for (var i = 1; i < cols.length; i++) {
		str += '\t' + cols[i];
	}
	str = str + '\n';
	for (var i = 0; i < rows.length; i++) {
		str += rows[i][cols[0]];
		for (var c = 1; c < cols.length; c++) {
			if(rows[i].hasOwnProperty(cols[c])){
				str += '\t' + rows[i][cols[c]];
			}else{
				str += '\t' + '';
			}
		}
		str = str + '\n';
	}
	return str;
}

function downloadHandler(value){
	$("#dialog_download").data("type",value);
	$("#dialog_download").dialog("open");
};

function selectItem(tr, select) {
	if (select == undefined) select = true;
	
	var item = table.items[tr.rowIndex-2];
	if (item.bin == '') return;
	
	if ($(tr).hasClass('row_selected') == select) return;
	$(tr).toggleClass('row_selected', select);
	
	// Two cases: user wants to either select or deselect the item.
	var bin = item.bin[0] == '~' ? item.bin.slice(1) : item.bin;
	if (select) {
		selected_items[bin].push(item);
	} else {
		var items = selected_items[bin];
		for (var i = 0; i < items.length; i++) {
			if (items[i] !== item) continue;
			items.splice(i, 1);
			break;
		}
	}
	
	// Enable "Edit" button if any items are selected.
	var any_selected = false;
	for_each(selected_items, function(items) {
		if (items.length > 0) any_selected = true;
	});
	$('#edit_item_button').button("option", "disabled", !any_selected);
	
	updateBinCounters();
}



function updateBinCounters() {
	if (protocol == undefined) return;
	
	for (var i = 0; i < protocol.input_bins.length; i++) {
		var bin = protocol.input_bins[i];
		var counter = $('.bin_counter[data-type="' + bin + '"]');
		var count = selected_items[bin].length;
		counter.text(count);
		counter.toggleClass('ok', count > 0);
	}
}


function updateToolbar() {
	if (protocol != undefined) {
		$('#new_item_button').hide();
		$('#edit_item_button').hide();
		$('#bin_counters').html('');
		for (var i = 0; i < protocol.input_bins.length; i++) {
			var bin = protocol.input_bins[i];
			$('#bin_counters').append(
				'<div class="bin_counter" data-type="' + bin + '" title="' + bin + '">0</div>');
			$('.bin_counter[data-type="' + bin + '"]').click(function() {
			    showSearchResults(selected_items);
			});
		}
	} else {
		$('#new_item_button').show();
		$('#edit_item_button').show();
		$('#edit_item_button').button('option', 'disabled', true);
	}
}

function startProtocol() {
	protocol_items = {};
	protocol_items['Instructions'] = protocol.instructions();
	protocol_items['Instructions'] = marked(protocol_items['Instructions']);
	protocol.output();
	protocol.input();
	protocol_items['selected'] = selected_items;
	
	showExperimentInstructions(protocol_items);

	experiment = {};
	experiment['json'] = protocol_items;
	experiment['protocol_id'] = protocol.id;
	experiment['protocol'] = protocol.name;

	var formData = new FormData();
	formData.append('json',JSON.stringify(experiment['json']));
	formData.append('protocol_id',protocol.id);
	formData.append('protocol',protocol.name);

	console.log(experiment);
	$.ajax({
		type: "POST",
		url: "/add_experiment",
		data: formData,
		success: function(data) {
			console.log(data);
			experiment['id'] = data.id;
			selected_items = {};
		},
		cache: false,
		contentType: false,
		processData: false
	});
	hideToolbar();
	
}

function hideToolbar() {
	//$("#protocol_drawer").toggleClass("start_experiment",true);
	$(".expr_button").show();
	$("#toolbar").slideUp();
	$("#search_form").slideUp();
}

function showToolbar() {
	//$("#protocol_drawer").toggleClass("start_experiment",false);
	$(".expr_button").hide();
	$("#toolbar").slideDown();
	$("#search_form").slideDown();
}

function returnHome() {
	selected_items = {};    // Selected items, grouped by bin.
	protocol = undefined;   // undefined -> No protocol selected.
	table = { items: [], columns: [], visible_cols: [] };
	protocol_items = undefined;
	experiment = undefined;
	//$('#protocol_drawer').slideUp();
	$("#protocol_title p").text('');
	$('#bin_counters').html('');
	$("#search").val('');
	$("#protocol_settings").html("");
	$("#experiment_wrapper").slideUp();
	updateToolbar();
	displayUserInfo(true);
	initUserInfo();
	showToolbar();
}

function runSearch(query) {
	$('#search').val(query);
	$.ajax({
		url:'/search/' + $('#search').val(),
		success: function(data) { showSearchResults(data); },
		beforeSend: function() { NProgress.start(); },
		complete: function() { NProgress.done(); }
	});
}

$(window).load(initUserInfo);

$(document).ready(function() {
	//Prevent normal drag and drop behaviour
	$(window).on("dragover",function(e){
		e = e || event; e.preventDefault();
	},false);
	$(window).on("drop",function(e){
		e = e || event; e.preventDefault();
	},false);

	$(window).scroll(function(){
		if($(window).scrollTop() + $(window).height() >= $(document).height()-150){
			console.log("lisataan");
			table_page++;
			addItems('table', table.items.slice(table_page*ITEMS_PER_PAGE,
				(table_page+1)*ITEMS_PER_PAGE), table.visible_cols);
		}
	});

	$(window).resize(function(event) {
		if($("#tab_content").children().length < 1){
			return;
		}else{
			resetHeaderWidth();
			$("#simpleMenu").position({my: 'right top', at:'left bottom-10px', of: $("#table_menu_button")});
		}
	});

	$("#protocol_gear").click(function() {
		$("#protocol_settings").slideToggle();
	});

	add_item_types = Object.keys(valid_item_types);
	// Initialize the "Add" button with available options.
	for (var i = 0; i < add_item_types.length; i++) {
		$("<li><a href='#'>" + add_item_types[i] + "</a></li>").appendTo($("#new_item_button").next()).click(function(event) {
			event.preventDefault();
			switch ($(this).text()) {
				case 'Protocol': toggleAddProtocol(); break;
				case 'Excel': toggleAddExcel(); break;
				default: toggleAdd($(this).text());
			}
		});
	};

	$("#logo").click(returnHome);

	$('#new_item_button').button({
		icons: { secondary: "ui-icon-triangle-1-s" }
	}).click(function() {
		var menu = $(this).next().toggle().position({
			my: "left top", at: "left bottom", of: this
		});
		$(document).one("click", function() { menu.hide(); });
		return false;
	}).next().hide().menu();

	$('#edit_item_button').button().click(function(event) {
		if (event.shiftKey) togglePowerEdit();
		else toggleEdit();
	});
	document.onkeypress = function(e) {
		if (e.keyCode == 32 && (e.target == document.body ||
			e.target == document.getElementById('secret'))) {
			toggleEdit();
			return false;
		}
	};

	$('#search_submit').click(function() {
		if($("#search").val() === ''){
			displayUserInfo(true); return false;
		}
		runSearch($('#search').val());
		return false;
	});

	$("#expr_home").button({
		icons: {secondary: "ui-icon-home" },
		label: "Home",
		text: true
	}).click(function() {
		var formData = new FormData();
		formData.append('json',JSON.stringify(experiment['json']));
		formData.append('id',experiment.id);

		$.ajax({
			type: "POST", url: "/update_experiment", data: formData,
			complete: returnHome,
			cache: false, contentType: false, processData: false
		});
	});

	$("#expr_finish").button({
		icons: {secondary: "ui-icon-check" },
		label: "Finish", text: true
	}).click(function() {
		finishExperiment(experiment.id);
	});
	
	$("#expr_cancel").button({
		icons: {secondary: "ui-icon-closethick" },
		label: "Cancel", text: true
	}).click(function(){
		console.log(experiment);
		$.get('/delete_experiment/'+experiment.id, returnHome);
	}).parent().buttonset();

	updateToolbar();
	
	var dialog_options = {
		autoOpen: false, modal: true, resizable: true, draggable: true,
		//dialogClass: "dialog_items",
		show: { effect: "fade", duration: 100 },
		hide: { effect: "fade", duration: 100 }
	};

	$("#download_button").button().click(function() {
		var data_str = tableToTSV();
		var data_type = $("#dialog_download").data("type");
		$('<a id="data_link" download="'+$("#download_name").val()+data_type+'" href="data:application/tsv;charset=UTF-8,'+encodeURIComponent(data_str)+'"> link</a>').appendTo($("#download_link_holder"));
		document.getElementById('data_link').click();
		$("#data_link").remove();
		$("#dialog_download").dialog('close');
		$("#download_name").val('');
	});

	$("#protocol_start").click(function(event) {
		startProtocol();
		return false;
	});

	$("#protocol_info").tooltip({position: { my: "left top+5", at: "left bottom", collision: "flipfit" }});

	$("#protocol_cancel").click(function(){
		returnHome();
	});


	$("#dialog_download").dialog({
		autoOpen: false,
		width: 500,
	});


	$("#dialog_edit_items").dialog($.extend({
		position: {my: 'center top', at: 'center top+130px', of: window,
			collision: 'none'},
		minWidth: 750, height: "auto",
		create: function(event, ui) {
			$('#dialog_edit_items ~ .ui-dialog-buttonpane').append(
				'<input id="add_attr_auto" class="init" ' +
				'value="Add new attribute"><button id="add_attr_button">' +
				'</button>');
		},
		close: function(event, ui) {
			$("#edit_items_form").html("");
		},
		open: function(event, ui) { initDialogOpen('dialog_edit_items'); },
		buttons: {
			Save: function(event) { sendItemsToServer(event, $(this)); },
			Cancel: function() { $(this).dialog('close'); }
		}
	}, dialog_options));

	
	$("#dialog_add_protocol").dialog($.extend({
		minHeight: 600, minWidth: 700, height: "auto", //width: "auto",

		close: function() {
			$(this).find("fieldset").children("div").html("");
			$(".protocol_type").hide();
		},
		buttons: {
			Save: function() {
				sendProtocolToServer();
				$(this).dialog("close");
				$(this).find("textarea").val("");
				$("#protocol_options").children("textarea").val(protocol_sample);
				$("#protocol_type_Add_Item").find("textarea").last().val('Attribute1:"default value"\nAttribute2:');
				$("#protocol_type_Add_Linker").find("textarea").last().val('Attribute1:"default value"\nAttribute2:');
				$("#protocol_type_select").prop("selectedIndex", 0);
			},
			Cancel: function() { 
				$(this).dialog('close');
				$(this).find("textarea").val("");
				$("#protocol_options").children("textarea").val(protocol_sample);
				$("#protocol_type_Add_Item").find("textarea").last().val('Attribute1:"default value"\nAttribute2:');
				$("#protocol_type_Add_Linker").find("textarea").last().val('Attribute1:"default value"\nAttribute2:');
				$("#protocol_type_select").prop("selectedIndex", 0);
			}
		}
	}, dialog_options));

	$("#dialog_excel_upload").dialog($.extend({
		minHeight: 500, minWidth: 500, height: "auto",
		create: function(event, ui) {
			
		},
		close: function(event, ui) {
			
		},
		open: function(event, ui) {},
		buttons: {
			Save: function() {
				var formData = new FormData();
				formData.append("type", "import");
				formData.append("name", $(this).data("excel_name"));
				console.log(formData);
				$.ajax({
					url: '/upload_excel',
					type: 'POST',
					success: function(d) { 
						console.log(d);
						$("#dialog_excel_upload").dialog("close");
						if(d.success){
							$("<ul><li><p>Added "+d.added +" items to database.</p></li>"+
								"</ul>").appendTo("#dialog_message");
							$("#dialog_message").dialog("open");
						}
					},
					error: function() {},
					data: formData,
					//Options to tell JQuery not to process data or worry about content-type
					cache: false, contentType: false, processData: false
				});
			  },
			Cancel: function() {
				var formData = new FormData();
				formData.append("type", "delete");
				formData.append("name", $(this).data("excel_name"));
				console.log(formData);
				$.ajax({
					url: '/upload_excel',
					type: 'POST',
					success: function(d) { 
						console.log(d);
						$("#dialog_excel_upload").dialog("close");
					},
					error: function() {},
					data: formData,
					//Options to tell JQuery not to process data or worry about content-type
					cache: false, contentType: false, processData: false
				});
			}
		}
	}, dialog_options));
	
	$("#protocol_type_select").change(function(event) {
		console.log(this, event);
		initProtocolFields($(this).find(":selected").val());

	});
	$(".protocol_type").hide();

	$("#dialog_message").dialog({
		minWidth: 100, minHeight: 100,
		autoOpen: false,
		position: {
			my: "right-20 top",
			at: "right bottom",
			of: "#header"
		},
		show: { effect: "slide", duration: 400 },
		hide: { effect: "slide", duration: 400 },
		open: function() {
			window.setTimeout(function() {
				$("#dialog_message").dialog("close");
			}, 2500);
		},
		close: function() { $("#dialog_message").html(""); }
	});
	
	$("#dialog_microscope").dialog($.extend({
		position: {my: 'center', at: 'center', of: window},
		open: function() { $('#dialog_microscope img').wheelzoom(); },
		buttons: {
			Close: function() { $(this).dialog('close'); }
		}
	}, dialog_options));

});

function initUserInfo(){
	$.ajax('/get_user_info', {
		success: function(d){
			console.log(d);
			user_info = d;

			$('#user_tile > p').html('Name: '+ user_info.user.name +
				'<br>Email: '+ user_info.user.email + '<br>Password: ' +
				'<span><a id="change_password" href="#">(change)</a></span>');
			$('#change_password').click(function() {
				$('#change_password').parent().html('<input id="new_password" type="text" name="new_password" placeholder="New password"></input>');
			});
			
			// Group memberships
			var tile = $('#groups_tile > ul').html('');
			for (var i = 0; i < user_info.groups.length; i++) {
				tile.append('<li>'+user_info.groups[i]+'</li>');
			};
			tile.append('<li><a href="#">Create a new group</a></li>');
			tile.append('<li><a href="#">Join a group</a></li>');
			tile.find('a').last().click(function() {
				if ($('#join_group_key').length) return;
				$('#groups_tile li:nth-last-child(3)').after(
					'<li><input id="join_group_key" type="text" name="email"' +
					'placeholder="Group key" /></li>');
				$('#join_group_key').focus().keyup(function(e) {
					if (e.keyCode != 13) return;
					$.post('/api/join_group', { password: e.target.value },
						function(d) {
						if (d.success)
							$('#join_group_key').parent().html(d.group_name);
						else
							$('#join_group_key')
								.css('background-color', '#faa')
								.animate({'background-color': 'white'}, 400);
					});
				});
			});
			
			// Ongoing experiments
			var tile = $('#experiments_tile > ul').html('');
			if (user_info.experiments.length < 1) {
				tile.append('<li>No recent experiments</li>');
			}else{	
				for (var i = 0; i < user_info.experiments.length; i++) {
					exp = user_info.experiments[i]
					if(exp['State'] === 'ONGOING'){
						$('<li><a href="#" data-id="'+exp.id+'">'+
							exp['Start Date']+ ' - ' +exp['Protocol name']+
							' ['+exp['State']+']</a></li>')
						.appendTo(tile).children('a').click(function(event) {
							event.preventDefault();
							modifyExperiment($(this).data("id"));
						});
					}else{
						tile.append('<li>'+exp['Start Date']+ ' - ' +
							exp['Protocol name']+ ' ['+exp['State']+']</li>');
					}
				}
			}

			var tile = $('#protocols_tile > ul').html('');
			for (var i = 0; i < user_info.protocols.length; i++){
				tile.append('<li>' + user_info.protocols[i]['name'] + '</li>');
				if(user_info.protocols[i]['type'] === 'Add_Item'){
					if(!valid_item_types.hasOwnProperty(user_info.protocols[i]['name'])){
						valid_item_types[user_info.protocols[i]['name']] = user_info.protocols[i]['id'];
						$("<li class='ui-menu-item' role='presentation'><a href='#'>" + user_info.protocols[i]['name'] + "</a></li>").appendTo($("#new_item_button").next()).click(function(event) {
							event.preventDefault();
							if(typeof(valid_item_types[$(this).text()]) === "number" ||
								typeof(valid_item_types[$(this).text()]) === "string"){
								$.ajax("/protocol/" + valid_item_types[$(this).text()], {
									dataType: 'script',
									success: function(d){
										protocol_items = {};
										protocol.output();
										toggleAdd(protocol.name);
										protocol = undefined;
									},
									error: function(a,b,c) {
										console.log([a,b,c]);
									}
								});
							}else{
								toggleAdd($(this).text());
							}
										
						});
						$('#new_item_button').next().hide().menu();
					}
				}
			}
			$('<li><a href="#">Add a new favorite protocol</a></li>').appendTo(tile)
				.children('a').click(function(e) {
					e.preventDefault(); runSearch('protocol');
				});

			$('#start_page .group_updates').remove();
			for (var g = 0; g < user_info.groups.length; g++) {
				$('#start_page').append(
					'<div class="group_updates" data-group="'+g+'"><h1>' +
					'Updates: ' +user_info.groups[g] + '</h1><ul></ul></div>');
				var tile = $('.group_updates[data-group="'+g+'"] > ul');
				var updates = user_info.group_updates[user_info.groups[g]];
				if (updates.length == 0) {
					tile.append('<li>No updates</li>');
					continue;
				}
				for (var u = 0; u < updates.length; u++)
					tile.append('<li>' + updates[u] + '</li>');
			}
		}
	});
}

function finishExperiment(id){

	var server_data = {};
	server_data['id'] = id;
	server_data['add'] = experiment.json.add;
	server_data['mod'] = experiment.json.mod;
	console.log(server_data);
	
	var headers = {};
	headers['Content-Type'] = 'application/json';

	$.ajax({
		type: "POST",
		headers: headers,
		url: "/finish_experiment",
		data: JSON.stringify(server_data),
		success: function(data) {
			//If update also update dataTable
			if (data.success) {
				returnHome();
				$("<ul><li><p>Added "+data.added +" items to database.</p></li>"+
					"<li><p>Modified "+data.modified +" items in the database</p></li>"+
					"</ul>").appendTo("#dialog_message");
				$("#dialog_message").dialog("open");
			}
		}
	});
}

function modifyExperiment(id) {
	console.log(id);
	$.ajax('/get_experiment_json/'+id, {
		success: function(d) {
			console.log(d, id);
			experiment = {};
			experiment['json'] = $.parseJSON(d.json);
			experiment['id'] = id;
			console.log(experiment.data);
			showExperimentInstructions(experiment.json);
			
			hideToolbar();
			 
		}
	});
}

function displayUserInfo(show) {
	if(show){
		destroyTabs();
		$("#start_page").show()
		$("#search_results").toggleClass('hidden',true);
	}else{
		$("#start_page").hide()
		$("#search_results").toggleClass('hidden',false);
	}
}

function destroyTabs(){
	remove_children(document.getElementById('tab_bar'));
	remove_children(document.getElementById('tab_content'));
}

function createTabs(tabs) {

	// Clear out existing tabs.
	destroyTabs();
	
	//Push Protocol as the last tab
	for (var i = 0; i < tabs.length; i++) {
		if(tabs[i].name.search(/protocol/i) != -1){
			tabs.push(tabs.splice(i,1)[0]);
		}
	};

	// Initialize the new tabs.
	for_each(tabs, function(tab, idx) {
		$('#tab_bar').append(
			'<li class="'+tab.class_name+'" data-tab="' + idx + '">' + tab.name + '</li>');
	});

	$('#tab_bar > li').click(function() {
		var idx = parseInt(this.dataset.tab);
		$('#tab_bar > li').removeClass('active').eq(idx).toggleClass('active');
		tabs[idx].renderer(document.getElementById('tab_content'));
		return false;
	});


	$("<div class='download_wrapper'><button class='download'>Excel</button><button class='download'>TSV</button></div>").appendTo($("#tab_bar")).children().first()
		.button({
			label: 'XLS'
		})
		.click(function() {
			downloadHandler('.xls');
		}).next()
		.button({
			label: 'TSV'
		})
		.click(function() {
			downloadHandler('.tsv');
		}).parent().buttonset();

	$('#tab_bar > li').eq(0).trigger('click');
}




function showSearchResults(results) {
	if (Object.keys(results).length == 0) return;   // FIXME: Inform user

	var tabs = [];
	for_each(results, function(items, type) {
		var tab_name = type + (typeof items === 'string' ? '' : ' (' + items.length + ')' );
		tabs.push({
			name: tab_name,
			renderer: function(div) { renderItems(div, items); },
			"class_name": ""
		});
	});
	displayUserInfo(false);
	createTabs(tabs);
	updateToolbar();
	updateBinCounters();
}

function showExperimentInstructions(experiment_items) {

	var tabs = [];
	var exp_keys = Object.keys(experiment_items).length;
	var exp_key_order = ['selected', 'mod', 'add', 'Instructions']
	var i = 0;

	for (i = 0; i < exp_key_order.length; i++) {
		var type = exp_key_order[i];
		var items = experiment_items[type];
		//For nested experiment tabs
		if(type !== 'Instructions'){
			var item_keys = Object.keys(items).length;
			for_each(items, function(samples, key){
				var class_name = (item_keys <= 1 ? "last" : "");
				var tab_name = key + (typeof samples === 'string' ? '' : ' (' + samples.length + ')' );
				tabs.push({
					name: tab_name,
					renderer: function(div) { renderItems(div, samples); },
					"class_name" : class_name
				});
				item_keys--;
			});
		}
		else{
			var tab_name = type + (typeof items === 'string' ? '' : ' (' + items.length + ')' );
			tabs.push({
				name: tab_name,
				renderer: function(div) { renderItems(div, items); },
				"class_name": ""
			});
		}
	};
	if(i < exp_keys){
		console.log("many keys");
		for_each(experiment_items, function(samples, key){
			if(exp_key_order.indexOf(key) === -1){
				var tab_name = key + (typeof samples === 'string' ? '' : ' (' + samples.length + ')' );
				tabs.push({
					name: tab_name,
					renderer: function(div) { renderItems(div, samples); },
					"class_name" : ""
				});
			}
		});
	}
	displayUserInfo(false);
	createTabs(tabs);
	updateToolbar();
	updateBinCounters();	
}

function renderItems(div, items) {
	if(typeof items === 'object'){
		if (protocol == undefined) {
			selected_items = {}
			selected_items[items[0].Type] = [];
		}

		// If the user is viewing protocols, show which are already selected.
		if (items[0].Type == 'Protocol') {
			for (var k = 0; k < items.length; k++){
				items[k].Selected = 'SELECT';
				for (var i = 0; i < user_info.protocols.length; i++) {
					if(items[k].id === user_info.protocols[i].id){
						items[k].Selected = 'SELECTED';
						break;
					}
				}

			}
		}

		calculateColumns(items);
		remove_children(div);
		$(div).html(
			'<table id="table" class="tabula" cellpadding="0" cellspacing="0" border="0"></table>');
		calculateItemBins();
		refreshTable();

		/*// If the user is viewing protocols, show which are already selected.
		if (items[0].Type == 'Protocol') {
			for (var k = 0; k < items.length; k++) {
				items[k].Selected = 'https://www.inzy.me/';
			}
		}*/
	}else{
		$(div).html(items);
	}

}

function calculateColumns(items){
	// Build a list of columns found in the given items.
	var columns = {};
	for (var i = 0; i < items.length; i++) {
		// No .hasOwnProperty() here, this loop needs to be *tight*.
		for (var key in items[i]) { columns[key] = true; }
	}
	columns = Object.keys(columns);
	
	table.items = items;
	table.columns = columns;
	
	var col_priority = column_priority['Unknown'];
	if (items[0]['Type'] in column_priority) {
		col_priority = column_priority[items[0]['Type']];
	}
	
	// We only show a maximum of eight columns. The columns we show
	// are selected based on a priority list of columns.
	table.visible_cols = [];
	for_each(col_priority, function(pcol) {
		if (table.visible_cols.length >= MAX_VISIBLE_COLS) return;
		if ($.inArray(pcol, columns) >= 0 && pcol != 'Type')
			table.visible_cols.push(pcol);
	});
	//If after priority list there is still space left show more
	if(table.visible_cols.length < MAX_VISIBLE_COLS){
		for_each(table.columns, function(col){
			if(table.visible_cols.length >= 8) return;
			if(col.indexOf('>') !== -1) return;
			if($.inArray(col,table.visible_cols) === -1){
				if(hidden_column(col)) return;
				table.visible_cols.push(col);
			}
		});
	}
	//If there is still space show linked columns
	if(table.visible_cols.length < MAX_VISIBLE_COLS){
		for_each(table.columns, function(col){
			if(table.visible_cols.length >= 8) return;
			if($.inArray(col,table.visible_cols) === -1){
				if(hidden_column(col)) return;
				table.visible_cols.push(col);
			}
		});
	}
}

function refreshTable(sort, asc) {

	buildTable('table', table.items.slice(0,ITEMS_PER_PAGE), table.visible_cols, sort, asc);

	$("#table tbody")[0].addEventListener("drop",function(ev) {
		ev.preventDefault();
		console.log(ev);
		console.log(ev.dataTransfer.types);
		var id = table.items[ev.target.parentElement.rowIndex-2].id;
		var attr = table.visible_cols[ev.target.cellIndex]
		if(ev.dataTransfer.types.indexOf("Files") === -1){
			var url = ev.dataTransfer.getData('Text');
			console.log(e=ev.target,id);
			sendURLtoServer(url,id, attr);
		}else{
			console.log(ev.dataTransfer.files);
			var file = ev.dataTransfer.files[0];
			sendFiletoServer(file,id, attr);
		}
	});

	// Construct the column visibility menu.
	var header_items = {};
	var sorted_columns = table.columns.slice(0).sort();
	for_each(sorted_columns, function(col) {
		var visible = $.inArray(col, table.visible_cols) >= 0;
		if (hidden_column(col)) return;
		var parts = col.split(' > ');
		
		// For each column, construct the necessary submenu hierarchy.
		var level = header_items;
		for (var p = 0; p < parts.length - 1; p++) {
			if (!level.hasOwnProperty(parts[p]))
				level[parts[p]] = { name: parts[p], items: {} };
			level = level[parts[p]].items;
		}
		level[parts[p]] = { 
			'name': parts[p],
			'selected': visible,
			'events': { 
				click: function(that) {
					var idx = $.inArray(col, table.visible_cols);
					if (idx === -1) {
						table.visible_cols.push(col);
						refreshTable();
						return true;
					} else {
						table.visible_cols.splice(idx, 1);
						refreshTable();
						return false;
					}
				}},
			'checkbox': true
		};
	});

	$("#table_menu_button").click(function(eventObj) {
		buildContextMenu({
			'anchor': $("#table_menu_button"), 
			'menu_items': header_items,
			'add_items': true,
			'header': 'Choose columns'
		});
		return false;
	});
	$("thead").on("contextmenu", function(eventObj) {
		eventObj.preventDefault();
		console.log(eventObj.which);
		buildContextMenu({
			'anchor': eventObj, 
			'menu_items': header_items,
			'add_items': false,
			//'header': 'Choose columns'
		});
		return false;
	});
	$("thead > tr > th").click(function() {
		console.log($(this).text());
		var column = $(this).text();
		var asc = $(this).hasClass("sorting_asc") ? false : true;
		sortItems(column,asc);
		
		refreshTable(column, asc);
	});
	// Build a set of selected items for fast membership queries.
	var selected = {};
	for_each(selected_items, function(items) {
		for_each(items, function(item) { selected[item.id] = true; });
	});
	
	// Highlight items if they are selected or not suitable for protocol.
	var tr = $('#table tbody tr');
	for_each(table.items, function(item, idx) {
		if (selected.hasOwnProperty(item.id)) {
			tr.eq(parseInt(idx)+1).toggleClass('row_selected', true);
		}
		
		if (item.bin == undefined) return;
		if (item.bin == '')
			tr.eq(parseInt(idx)+1).toggleClass('invalid', true);
		else if (item.bin.indexOf('~') == 0)
			tr.eq(parseInt(idx)+1).toggleClass('red', true);
		if(item.hasOwnProperty("Selected")){
			if(item.Selected === "SELECTED"){
				tr.eq(parseInt(idx)+1).toggleClass('invalid', true);
			}
		}
	});

	var context_menu_items = {
		'select': {
			'name': 'Select all',
			'events': {
				click: function(that) {
					$('#table tbody tr').slice(1).each(function() {
						selectItem(this);
					});
				}
			},
			'checkbox': false
		},
		'deselect': {
			'name': 'Deselect all',
			'events': {
				click: function(that) {
					$('#table tbody tr').slice(1).each(function() {
						selectItem(this, false);
					});
				}
			},
			'checkbox': false
		},
	};
	//If user is viewing protocols add protocol adding
	if(table.items[0].Type === 'Protocol'){
		context_menu_items['add_protocol'] = 
		{
			'name': 'Add Protocol',
			'events': {
				click: function(that) {
					$(".row_selected").each(function(index, ele){
						var protocol = table.items[this.rowIndex-2];
						
						$.get('/user_add_protocol/'+protocol.id, function(d){
							if(d.success){
								user_info.protocols.push(d.added);
								$("<p>"+d.added.name+" added</p>").appendTo("#dialog_message");
								$("#dialog_message").dialog("open");
							}
						});
					});
				}
			},
			'checkbox': false
		};
	}
	for (var i = 0; i < user_info.protocols.length; i++) {
		if(user_info.protocols[i].type === "Add_Item") continue;
		if(context_menu_items.protocols === undefined){
			context_menu_items.protocols = {'name': 'Procotols', 'items': {}};
		}
		context_menu_items.protocols.items[user_info.protocols[i].name] = {
			'name': user_info.protocols[i].name,
			'data': {'id': user_info.protocols[i].id}
		};
		if(user_info.protocols[i].type === "Add_Linker"){
			if(!valid_item_types.hasOwnProperty(user_info.protocols[i]['name'])){
				valid_item_types[user_info.protocols[i]['name']] = user_info.protocols[i]['id'];
			}
			context_menu_items.protocols.items[user_info.protocols[i].name]["events"] = {
				click: function(that){
					if(typeof(valid_item_types[$(that).children("label").text()]) !== "object"){
						$.ajax("/protocol/" + valid_item_types[$(that).children("label").text()], {
							dataType: 'script',
							success: function(d){
								protocol_items = {};
								protocol.output();
								toggleAdd(protocol.name);
								protocol = undefined;
							},
							error: function(a,b,c) {
								console.log([a,b,c]);
							}
						});
					}else{
						toggleAdd($(that).children("label").text());
					}
				}
			};
		}else{
			context_menu_items.protocols.items[user_info.protocols[i].name]["events"] = {
				click: function(that) {
					selectProtocol(that.dataset.id);
				}
			};
		}
	};


	$("tbody").on("contextmenu", function(eventObj){
		eventObj.preventDefault();
		buildContextMenu({
			'anchor': eventObj,
			'menu_items': context_menu_items,
			'close_on_select': true
		});
	})
	

	if(experiment === undefined){
		// Make table cells multi-selectable
		toggleSelectable();
	}
	else{
		toggleExperimentEdit();
	}
}

function initDialogOpen(id) {
	function initTextarea(that) {
		$(that).focus(function() {
			$(this).toggleClass('grey', false);
			$(this).toggleClass('init', false);
			if ($(this).val() == 'Multiple values') $(this).select();
		}).blur(function() {
			if ($(this).val() === '') {
				var text = "";
				if(this.dataset.hasOwnProperty("def")){
					text = this.dataset["def"].indexOf('|') !== -1 ? 'Multiple values' : this.dataset["def"];
				}
				$(this).val(text).trigger('autosize');				
				$(this).toggleClass('init', true);
			}
			if ($(this).val() === 'Multiple values') {
				$(this).toggleClass('grey', true);
				$(this).toggleClass('init', true);
			}
			$(".edit_info").remove();
		});
	}

	$("#add_attr_button").unbind();
	$("#add_attr_button").button({
		icons: { primary: "add_button_icon" }, text: false
	}).click(function() {
		attr_val = $("#add_attr_auto").val();
		var textarea = $('<div class="dialog_edit_items_attr_container"><label class="label" for="' + attr_val + '">' + attr_val + '</label>' + '<textarea class="attr_textarea init grey" form="dialog_edit_items_form" name="' + attr_val + '" rows="1" data-def=""></textarea></div>').insertAfter($("#edit_items_form > div").last());

		textarea.autosize();

		$("#add_attr_auto").val('Add new attribute').toggleClass('init');
		initTextarea(textarea.children('textarea'));
	});

	$("#edit_items_form textarea").autosize();
	$("#edit_items_form textarea").each(function() {
		initTextarea(this);
	});
}


function initProtocolFields(value){
	console.log(value);
	$(".normal_protocol_settings").hide();
	if(value === 'Protocol'){
		$(".normal_protocol_settings").show();		
	}
	$("#protocol_options > textarea").val(protocol_sample_texts[value]);
	$("#protocol_tabs").tabs({heightStyle: "auto"});
	$(".protocol_type").show();
}


function selectProtocol(id) {
	$.ajax('/protocol/' + id, {
		dataType: 'script',
		success: function(d){			
			protocol.id = id;
			$("#protocol_title p").text(protocol.name);
			//$('#protocol_drawer').slideToggle();
			$('#protocol_button').hide();

			selected_items = {};
			for_each(protocol.input_bins, function(bin_name) {
				selected_items[bin_name] = [];
			});
			showProtocolDetails();
			updateToolbar();
			calculateItemBins();
			$(".row_selected").each(function(index, element){
				selectItem(this, false);
				selectItem(this);
			});
			refreshTable();
		},
		error: function(a,b,c) {
			console.log([a,b,c]);
		}
	});
}


function showProtocolDetails() {

	$("#protocol_info").attr("title", protocol.description);
	$("#protocol_settings").html("");
	var left = true;
	for (var key in protocol.settings) {
		if (protocol.settings.hasOwnProperty(key)) {
			var container = $("#protocol_settings");
			left = !left;
			switch (protocol.settings[key].type) {
			case "slider":
				$('<p><label>' + key.replace('_',' ') + ':</label><input type="text"></p> <div id="' + key.replace(' ', '_') + '" class="slider"></div>').appendTo(container);
				protocol.options[key.replace(' ', '_')] = 0;
				$("#" + key.replace(' ', '_')).slider({
					range: "min",
					value: parseFloat(protocol.settings[key].range.split("-")[0]),
					min: parseFloat(protocol.settings[key].range.split("-")[0]),
					max: parseFloat(protocol.settings[key].range.split("-")[1]),
					slide: function(event, ui) {
						$(this).prev().children("input[type='text']").val(ui.value);
					},
					stop: function(event, ui) {
						protocol.options(this.id, ui.value);
					}
				});
				$(container).find("input").last().val($("#" + key.replace(' ', '_')).slider("value"));
				break;
			case "checkbox":
				var values = protocol.settings[key].range.replace(/[\[\]'']/g, '').split(",");
				var check_str = '<p><label class="block">' + key.replace('_',' ') + ':</label>';
				for (var i = 0; i < values.length; i++) {
					check_str += '<input type="checkbox" class="' + key.replace(' ', '_') + '" value="' + values[i].trim() + '"><label>' + values[i].replace('_',' ') + '</label>';
					protocol.options(key.replace(' ', '_'), '');
				};
				check_str += '</p>';
				$(check_str).appendTo(container);
				$("." + key).click(function() {
					if ($(this).is(':checked')) {
						protocol.options(this.className, $(this).val());
					} else {
						protocol.options(this.className, '');
					}
				});
				break;
			case "radio":
				var values = protocol.settings[key].range.replace(/[\[\]'']/g, '').split(",");
				var radio_str = '<p><label class="block">' + key.replace('_',' ') + ':</label>';
				for (var i = 0; i < values.length; i++) {
					radio_str += '<input type="radio" class="' + key.replace(' ', '_') + '" name="' + key.replace(' ', '_') + '" value="' + values[i].trim() + '"><label>' + values[i].trim().replace('_',' ') + '</label>';
				};
				protocol.options(key.replace(' ', '_'), '');
				radio_str += '</p>';
				$(radio_str).appendTo(container);
				$("." + key.replace(' ', '_')).click(function() {
					protocol.options(this.className, $(this).val());
				});
				break;
			default:
				console.log("ERROR: wrong settings type");
				break;
			}

		}
	}

	$("#experiment_wrapper").slideDown();
}



function toggleAdd(type) {
	$("#dialog_edit_items h1").text(
		"Add new " + type.toLowerCase() + " to database")
	$('#edit_items_form').html('');

	// Add distinct attributes to new attribute input
	$("#add_attr_auto").val("Add new attribute");
	$("#add_attr_auto").focus(function() {
		$(this).val('').toggleClass('init', false);
	});
	$("#add_attr_auto").autocomplete({ source: suggested_columns });

	$('#dialog_edit_items ~ .ui-dialog-buttonpane .add_item_amount').remove();
	$('#dialog_edit_items ~ .ui-dialog-buttonpane').append(
		'<div class="add_item_amount"><label>Amount: </label><input id="item_amount" type="text" size="4" value="1"></div>'
	);

	// When item type is selected cycle through predefined default attributes
	// to add textareas to the form
	
	var fields = [];
	if (Object.keys(valid_item_types).indexOf(type) != -1)
		fields = valid_item_types[type];

	var add_form = constructEditForm(fields);

	/*var readonly = "";
	var add_form = "";
	for (var i = 0; i < fields.length; i++) {
		var value = "";
		if(valid_item_types.hasOwnProperty(type)){
			if(fields[i] == 'Type'){
				value = valid_item_types[type]['Type'] === undefined ? type : valid_item_types[type]['Type'];
			}else if(fields[i].indexOf('%') !== -1){
				if(valid_item_types[type][fields[i]] === undefined || 
					valid_item_types[type][fields[i]] === ""){
					value = "Linker attribute";
					readonly = "readonly";
				}else{
					 value = valid_item_types[type][fields[i]];
				}

			}else{
				value = valid_item_types[type][fields[i]] === undefined ? '' : valid_item_types[type][fields[i]];
			}

		}
		add_form += '<div class="dialog_edit_items_attr_container"><label class="label">' + fields[i] + '</label>' + '<textarea class="attr_textarea init" name="' + fields[i] + '" rows="1" '+readonly+'>' + value + '</textarea></div>';
		readonly = "";
	};*/
	$('#edit_items_form').append(add_form);
	$("#dialog_edit_items").dialog("open");
}

function toggleAddProtocol() {
	$("#dialog_add_protocol").dialog("open");
}




function toggleAddExcel() {
	//Can't listen on cancel click on file dialog so remove any existing inputs
	$("#excel_input").remove();
	$('<input id="excel_input" class="noSize" name="file" type="file" />')
		.appendTo($("body"))
		.change(function(){
			var formData = new FormData();
			formData.append("excel", document.getElementById('excel_input').files[0]);
			formData.append("type", "analyze");
			console.log(formData);
			$.ajax({
				url: '/upload_excel',
				type: 'POST',
				success: function(d) { 
					console.log(d);
					attributes = "";
					for (var i = 0; i < d.Attributes.length; i++) {
						attributes += "<li>"+d.Attributes[i]+"</li>";
					};
					$("#dialog_excel_upload > ul").html(attributes);
					$("#dialog_excel_upload").find("span").html(d.Amount);
					$("#dialog_excel_upload").data("excel_name", d.file);
					$("#dialog_excel_upload").dialog("open");
					//Can't reset the file input so remove it
					$("#excel_input").remove();
				},
				error: function() {
					$("#excel_input").remove();
				},
				data: formData,
				//Options to tell JQuery not to process data or worry about content-type
				cache: false, contentType: false, processData: false
			});
		}).click();
}



function toggleEdit() {

	$("#dialog_edit_items").data("type", 'edit');
	// Determine which attributes have multiple values and which are shared.
	var columns = {};
	var item_length = 0;
	for_each(selected_items, function(items) {
		item_length = items.length;
		for (var i = 0; i < items.length; i++) {
			for_each(items[i], function(val, key) {
				if (hidden_column(key)) return;
				if (!columns.hasOwnProperty(key)) {
					columns[key] = {"attrs":[val], "counter":0};
				}else if(columns[key].attrs.indexOf(val) === -1){
					columns[key].attrs.push(val);
				}
				columns[key].counter++;
			});
		}
	});

	for_each(columns, function(item, key){
		if(item_length !== item.counter)
			item.attrs.push("' '");
		columns[key] = item.attrs;
	});

	$('#dialog_edit_items ~ .ui-dialog-buttonpane .add_item_amount').remove();

	// Don't open a dialog if it's already open or nothing is selected.
	if ($('#dialog_edit_items').is(':visible')) return;
	if (!Object.keys(columns).length) return;

	var edit_form = constructEditForm(columns);	
	
	$('#edit_items_form').append(edit_form);
	$('#dialog_edit_items h1').html('Edit selected items');

	$("#dialog_edit_items textarea").tooltip({
		tooltipClass:"edit_info"
	});

	$("#dialog_edit_items").dialog("open");

	$("#add_attr_auto").focus(function() {
		$(this).val('').toggleClass('init', false);
	});
	$("#add_attr_auto").autocomplete({ source: suggested_columns });
}

function constructEditForm(columns){
	// Split linked attributes into groups.
	var base = {};
	var groups = {};
	for_each(columns, function(val, key) {
		var parts = key.split(' > ');
		if (parts.length > 1) {
			if(val === "Linker attribute"){
				var group = parts.slice(0, parts.length - 2).join(' > ');	
			}else{
				var group = parts.slice(0, parts.length - 1).join(' > ');
			}
			if (!groups.hasOwnProperty(group)) groups[group] = {};
			groups[group][key] = val;
		} else {
			base[key] = val;
		}
	});
	
	// Construct the edit form.
	function textarea(key, val) {
		var text = typeof(val) !== 'string' ? (val.length > 1 ? 'Multiple values' : val[0]) : val;
		var data = typeof(val) !== 'string' ? val.join(' | ') : val;
		var init_class = typeof(val) !== 'string' ? 'grey' : '';
		return '<div class="dialog_edit_items_attr_container"><label class="label" for="' + key + '">' +
			key + '</label>' +

			'<textarea ' +/*title ="'+ data+'"*/ 'name="' + key + '" class="attr_textarea init ' +
			init_class + '" rows="1" data-def="'+data+'">' + text + '</textarea> </div>';

	}
	
	var edit_form = '';
	for_each(base, function(val, key) {
		edit_form += textarea(key, val);
	});

	for_each(groups, function(group, group_name) {
		edit_form += '<fieldset data-type="'+group_name+'"><legend>' + group_name + ' Attributes</legend>';
		for(var key in group){
			if(group.hasOwnProperty(key)){
				edit_form += textarea(key.replace(group_name+' > ', "").trim(), group[key]);	
			}
		}
		/*for_each(group, function(val, key) {			
			edit_form += textarea(key.split('>').pop().trim(), val);
		});*/
	});

	return edit_form;
}


function sendItemsToServer(eventObj, dialog) {
	var add = $(dialog).data("type") === 'edit' ? false : true;
	var updates = {};
	var linker_protocols = {};
	// Find all updated textareas and their values
	$(dialog).find("textarea").each(function() {
		//if ($(this).val() == 'Multiple values') return;   // FIXME
		if ($(this).hasClass('init') && !add) return;
		if ($(this).val() == '' && add) return;  // No empty fields

		var type = '';
		if ($(this).parents("fieldset").length >= 1)
			type = $(this).parents("fieldset").data('type');

		if (!updates.hasOwnProperty(type)) updates[type] = { changes: {} };

		if(add)
		{
			updates[type]['amount'] = $("#item_amount").val();
		}else{
			updates[type]['amount'] = 1;
		}

		//Check if we are dealing with linker protocol
		if($(this).attr('name').indexOf('%') === 0 && $(this).val() === 'Linker attribute'){
			linker_protocols[type] = $(this).attr('name').slice(1).split(">");
		}
		updates[type].changes[$(this).attr('name')] = $(this).val();
	});

	//If we have linker protocol copy updates item template to all selected items
	if(Object.keys(linker_protocols).length > 0){
		for_each(linker_protocols, function(val, key){
			var items = selected_items[val[0].trim()];
			for (var i = 0; i < items.length; i++) {
				updates[key + i] = {};
				$.extend(true, updates[key + i], updates[key]);
				updates[key + i].changes['%'+ val.join(">")] = items[i][val[1].trim()];
			}
			console.log(updates);
			delete updates[key];
		})
	}

	// Include sample IDs if we are editing.
	if (!add) {
		for (var type in updates) updates[type].sample_ids = [];
		for (var key in selected_items) {
			for (var i = 0; i < selected_items[key].length; i++) {
				var item = selected_items[key][i];

				for (var type in updates) {
					var prefix = (type == '' ? '' : type + ' > ');
					if (!item.hasOwnProperty(prefix + 'id')) continue;

					var item_id = item[prefix + 'id'];
					if (updates[type].sample_ids.indexOf(item_id) == -1)
						updates[type].sample_ids.push(item_id);

					for (var attr in updates[type].changes) {
						if (updates[type].changes[attr] == '')
							delete item[prefix + attr];
						else
							item[prefix + attr] = updates[type].changes[attr];
					}
				}
			}
		}
	}
	
	var doneButton = $(eventObj.target).parent();
	console.log(updates);

	$.ajax({ type: "POST", url: "/update",
		headers: { 'Content-Type': 'application/json' },
		data: JSON.stringify(updates),
		beforeSend: function() {
			doneButton.button("option", "disabled", true);
		},
		complete: function() {
			doneButton.button("option", "disabled", false);
			$(dialog).dialog("close");
		},
		success: function(d) {
			console.log(d);
			$("<ul><li><p>Added "+d.added +" items to database.</p></li>"+
				"<li><p>Modified "+d.modded +" items in the database</p></li>"+
				"</ul>").appendTo("#dialog_message");
			$("#dialog_message").dialog("open");
			
			if(table.items.length > 0)
				refreshTable();
		}
	});
}

function sendProtocolToServer() {

	var protocol_type = $("#protocol_type_select").find(":selected").val();

	var post_data = {
		settings: $(".protocol_settings:visible").find("textarea").last().val(),
		name: $(".protocol_settings:visible").find("textarea").first().val(),
		description: false,
		instructions: false,
		type: protocol_type
	};

	if(protocol_type === "Protocol"){
		post_data["instructions"] = $("#add_protocol_instr").find("textarea").first().val();
		post_data["description"] = $(".protocol_settings:visible").find("textarea").eq(1).val();
	}


	console.log(post_data);

	$.ajax({
		type: "POST",
		headers: { 'Content-Type': 'application/json' },
		url: "/add_protocol",
		data: JSON.stringify(post_data),
		success: function(d) {
			console.log(d);
			$("<ul><li><p>Added "+d.added.name +" protocol to database.</p></li>"+
				"</ul>").appendTo("#dialog_message");
			$("#dialog_message").dialog("open");
		}
	});
}

function sendURLtoServer(url, id, attr){

	var server_data = {
		def: {
			sample_ids: [id],
			changes: {}
		}
	};
	server_data.def.changes[attr] = url;
	//Construct data to server
	var headers = {};
	headers['Content-Type'] = 'application/json';

	$.ajax({
		type: "POST",
		headers: headers,
		url: "/update",
		data: JSON.stringify(server_data),
		success: function(data) {
			//If update also update dataTable
			if (data.success) {
			//	$.get('/search/' + query, showSearchResults);
			}
		}
	});

}

function sendFiletoServer(file, id, attr){
	console.log(file, id);

	var formData = new FormData();
	formData.append("blob", file);
	formData.append("sample_id", id);
	formData.append('attr', attr);
	console.log(formData);
	$.ajax({
		url: '/upload_blob',
		//server script to process data
		type: 'POST',
		//Ajax events
		beforeSend: function() {},
		success: function(d) {
			console.log(d);
		},
		error: function() {},
		data: formData,
		//Options to tell JQuery not to process data or worry about content-type
		cache: false,
		contentType: false,
		processData: false
	});
}


function calculateItemBins() {
	if (protocol == undefined || protocol_items != undefined) {
		// No protocol selected: item bin = item type.
		for_each(table.items, function(item) { item.bin = item.Type; });
	} else {
		// Protocol selected: use protocol selector() to determine bin.
		for_each(table.items, function(item, idx) {
			item.bin = protocol.selector(item);
		});
	}
}

function togglePowerEdit() {
	console.log("poweredit");
	// Make individual table cells editable. As an optimization, we only
	// initialize the cells as jEditable when the user clicks on them.
	//$("#search_results tbody.ui-selectable").selectable('destroy');


	$('#table').click(function(event) {
		$(event.target).editable(function(value,settings){

			var column = $("thead th")[this.cellIndex].innerText;
			var item = table.items[this.parentNode.rowIndex-2];
			item[column] = value;
			server_data = {def: { sample_ids: [], changes: {} }};
			server_data.def.sample_ids.push(item.id);
			server_data.def.changes[column] = value;
			var headers = {};
			headers['Content-Type'] = 'application/json';

			$.ajax({
				type: "POST",
				headers: headers,
				url: "/update",
				data: JSON.stringify(server_data),
				success: function(data) {
					//If update also update dataTable
					if (data.success) {
					//	$.get('/search/' + query, showSearchResults);
					}
				}
			});

			return value;
		}, 
		{
			cssclass: 'editable',
			placeholder: '',
			onblur: 'submit',
			event: 'edit', // Can't use "click", otherwise endless loop.
		}).trigger('edit');
	});
}

function toggleExperimentEdit() {
	console.log("experimentEdit");
	// Make individual table cells editable. As an optimization, we only
	// initialize the cells as jEditable when the user clicks on them.

	$('#table tbody').click(function(event) {
		$(event.target).editable(function(value,settings){
			console.log(a = this);
			var column = $("thead th")[this.cellIndex].innerText;
			var idx = this.parentNode.rowIndex-2;
			for_each(experiment.json, function(items,key){
				var bin = $(".active").text().split(' ').slice(0,-1).join(' ');
				if(items.hasOwnProperty(bin)){
					var item = items[bin][idx]
					console.log(item, column);
					item[column] = value;
					table.items = items;
					return;
				}
			});
			return value;
		}, 
		{
			cssclass: 'editable',
			placeholder: '',
			onblur: 'submit',
			event: 'edit', // Can't use "click", otherwise endless loop.
		}).trigger('edit');
	});
}


function toggleSelectable() {
	var select_mode = undefined;
	var range = undefined;
	
	$('#table tbody').mousedown(function(e) {
		if (e.which != 1) return;
		var tr = e.target.parentNode;
		select_mode = !$(tr).hasClass('row_selected');
		selectItem(tr, select_mode);
		$('#search').blur(); $(document).focus();  // Allow space key for edit
		range = [tr.rowIndex - 1, tr.rowIndex - 1];
		return false;
	}).mouseover(function(e) {
		if (select_mode == undefined) return;
		var tr = e.target.parentNode;
		for (var k = tr.rowIndex - 1; k < range[0]; k++)
			selectItem(tr.parentNode.childNodes[k], select_mode);
		for (var k = range[1] + 1; k <= tr.rowIndex - 1; k++)
			selectItem(tr.parentNode.childNodes[k], select_mode);
		range = [Math.min(range[0], tr.rowIndex - 1),
			Math.max(range[1], tr.rowIndex - 1)];
	}).bind('selectstart', function() { return false; });  // For IE
	
	$(document).mouseup(function() {
		select_mode = undefined;
	});

	$("#table tbody").on("contextmenu", function(e) {
		var tr = e.target.parentNode;
		selectItem(tr, true);
		$('#search').blur(); $(document).focus(); 
	});
}

